/***********************************************************************************
    Filename: hal_ext_int.c

    Copyright 2007 Texas Instruments, Inc.
***********************************************************************************/

/************************************************************************/
/*                           File included                              */
/************************************************************************/

#include "typedef.h"
#include "macros.h"
#include "board.h"
#include "hal_int.h"
#include "hal_ext_int.h"

/************************************************************************/
/*                           Static variable define                     */
/************************************************************************/
static ISR_FUNC_PTR ext_int0_isr = {0};
static ISR_FUNC_PTR ext_int1_isr = {0};
static ISR_FUNC_PTR ext_int2_isr = {0};


INT8U halExtIntConnect(INT8U ext_int_num, ISR_FUNC_PTR func);
INT8U halExtIntEnable(INT8U ext_int_num);
INT8U halExtIntDisable(INT8U ext_int_num);
INT8U halExtIntClear(INT8U ext_int_num);
INT8U halExtIntSetType(INT8U ext_int_num, INT8U type);


//----------------------------------------------------------------------------------
//  INT8U halExtIntConnect(INT8U ext_int_num, ISR_FUNC_PTR func)
//
//  DESCRIPTION:
//    Connect the extern int interrupt with the user defined ISR function 
//
//  ARGUMENTS:
//    ext_int_num  - extern int interrupt number 
//    func         - user defined ISR function
//
//  RETURNS:
//    HAL_EXT_INT_OK  - the connect operation success
//----------------------------------------------------------------------------------
INT8U halExtIntConnect(INT8U ext_int_num, ISR_FUNC_PTR func)
{
    istate_t key;
    HAL_INT_LOCK(key);
    switch (ext_int_num)
    {
        case HAL_AVR_INT0: ext_int0_isr = func; break;
        case HAL_AVR_INT1: ext_int1_isr = func; break;
        case HAL_AVR_INT2: ext_int2_isr = func; break;
        default: HAL_INT_UNLOCK(key); return(HAL_EXT_INT_ERROR);
    }
    halExtIntClear(ext_int_num);
    HAL_INT_UNLOCK(key);
    return(HAL_EXT_INT_OK);
}


//----------------------------------------------------------------------------------
//  INT8U halExtIntEnable(INT8U ext_int_num)
//
//  DESCRIPTION:
//    Enable the extern int interrupt  
//
//  ARGUMENTS:
//    ext_int_num  - extern int interrupt number 
//
//  RETURNS:
//    HAL_EXT_INT_OK    - the connect operation success
//    HAL_EXT_INT_ERROR - the interrupt enable error
//----------------------------------------------------------------------------------
INT8U halExtIntEnable(INT8U ext_int_num)
{    
    switch (ext_int_num)
    {
        case HAL_AVR_INT0: GICR |= BV(INT0);  break;
        case HAL_AVR_INT1: GICR |= BV(INT1);  break;
        case HAL_AVR_INT2: GICR |= BV(INT2);  break;
        default: return(HAL_EXT_INT_ERROR);
    }
    return(HAL_EXT_INT_OK);
}

//----------------------------------------------------------------------------------
//  INT8U halExtIntDisable(INT8U ext_int_num)
//
//  DESCRIPTION:
//    Disable the extern int interrupt  
//
//  ARGUMENTS:
//    ext_int_num  - extern int interrupt number 
//
//  RETURNS:
//    HAL_EXT_INT_OK    - the connect operation success
//    HAL_EXT_INT_ERROR - the interrupt enable error
//----------------------------------------------------------------------------------
INT8U halExtIntDisable(INT8U ext_int_num)
{
    switch (ext_int_num)
    {
        case HAL_AVR_INT0: GICR &=~BV(INT0);  break;
        case HAL_AVR_INT1: GICR &=~BV(INT1);  break;
        case HAL_AVR_INT2: GICR &=~BV(INT2);  break;
        default: return(HAL_EXT_INT_ERROR);
    }
    return(HAL_EXT_INT_OK);
}

//----------------------------------------------------------------------------------
//  INT8U halExtIntClear(INT8U ext_int_num)
//
//  DESCRIPTION:
//    Clear the extern int interrupt flag 
//
//  ARGUMENTS:
//    ext_int_num  - extern int interrupt number 
//
//  RETURNS:
//    HAL_EXT_INT_OK    - the connect operation success
//    HAL_EXT_INT_ERROR - the interrupt enable error
//----------------------------------------------------------------------------------
INT8U halExtIntClear(INT8U ext_int_num)
{
    switch (ext_int_num)
    {
        case HAL_AVR_INT0: GIFR |= BV(INTF0);  break;
        case HAL_AVR_INT1: GIFR |= BV(INTF1);  break;
        case HAL_AVR_INT2: GIFR |= BV(INTF2);  break;
        default: return(HAL_EXT_INT_ERROR);
    }
    return(HAL_EXT_INT_OK);
}

//----------------------------------------------------------------------------------
//  INT8U halExtGetFlag(INT8U ext_int_num)
//
//  DESCRIPTION:
//    Get the extern int interrupt flag 
//
//  ARGUMENTS:
//    ext_int_num  - extern int interrupt number 
//
//  RETURNS:
//    HAL_EXT_INT_OK    - the connect operation success
//    HAL_EXT_INT_ERROR - the interrupt enable error
//----------------------------------------------------------------------------------
INT8U halExtIntGetFlag(INT8U ext_int_num)
{
   INT8U ext_flag;
   switch (ext_int_num)
    {
        case HAL_AVR_INT0: ext_flag = GIFR & BV(INTF0);  break;
        case HAL_AVR_INT1: ext_flag = GIFR & BV(INTF1);  break;
        case HAL_AVR_INT2: ext_flag = GIFR & BV(INTF2);  break;
        default: return(HAL_EXT_INT_ERROR);
    }
    return ext_flag;
}

//----------------------------------------------------------------------------------
//  INT8U halExtIntSetType(INT8U ext_int_num, INT8U type)
//
//  DESCRIPTION:
//    Set the extern int interrupt type
//      1.Low level trigger;
//      2.Any change;
//      3.Falling edge trigger;
//      4.Rising edge trigger.
//
//  ARGUMENTS:
//    ext_int_num  - extern int interrupt number 
//    type         - the extern interrupt trigger type, describe as below
//      1.HAL_EXT_INT_LOW_LEVEL            
//      2.HAL_EXT_INT_ANY_CHANGE           
//      3.HAL_EXT_INT_FALLING_EDGE         
//      4.HAL_EXT_INT_RISING_EDGE         
//
//  RETURNS:
//    HAL_EXT_INT_OK    - the connect operation success
//    HAL_EXT_INT_ERROR - the interrupt enable error
//----------------------------------------------------------------------------------
INT8U halExtIntSetType(INT8U ext_int_num, INT8U type)
{
    INT8U temp;
    switch(type)
    {
        case HAL_EXT_INT_LOW_LEVEL:            
            switch(ext_int_num)
            {
                case HAL_AVR_INT0 : 
                                    temp = MCUCR & 0xFC;
                                    temp |= HAL_EXT_INT_LOW_LEVEL;
                                    MCUCR = temp; 
                                    break;
                case HAL_AVR_INT1 : temp = MCUCR & 0xF3;
                                    temp |= HAL_EXT_INT_LOW_LEVEL << 2;
                                    MCUCR = temp;
                case HAL_AVR_INT2 : return(HAL_EXT_INT_ERROR);
                default: return(HAL_EXT_INT_ERROR);
            }
            break;

         case HAL_EXT_INT_ANY_CHANGE:
            switch(ext_int_num)
            {
                case HAL_AVR_INT0 : 
                                    temp = MCUCR & 0xFC;
                                    temp |= HAL_EXT_INT_ANY_CHANGE;
                                    MCUCR = temp; 
                                    break;
                case HAL_AVR_INT1 : temp = MCUCR & 0xF3;
                                    temp |= HAL_EXT_INT_ANY_CHANGE << 2;
                                    MCUCR = temp;
                case HAL_AVR_INT2 : return(HAL_EXT_INT_ERROR);
                default: return(HAL_EXT_INT_ERROR);
            };
         case HAL_EXT_INT_FALLING_EDGE:
            switch(ext_int_num)
            {
                case HAL_AVR_INT0 : 
                                    temp = MCUCR & 0xFC;
                                    temp |= HAL_EXT_INT_FALLING_EDGE;
                                    MCUCR = temp; 
                                    break;
                case HAL_AVR_INT1 : temp = MCUCR & 0xF3;
                                    temp |= HAL_EXT_INT_FALLING_EDGE << 2;
                                    MCUCR = temp;
                case HAL_AVR_INT2 : MCUCSR &=~BV(ISC2);break;
                default: return(HAL_EXT_INT_ERROR);
            };
            break;
         case HAL_EXT_INT_RISING_EDGE:
            switch(ext_int_num)
            {
                case HAL_AVR_INT0 : 
                                    temp = MCUCR & 0xFC;
                                    temp |= HAL_EXT_INT_RISING_EDGE;
                                    MCUCR = temp; 
                                    break;
                case HAL_AVR_INT1 : temp = MCUCR & 0xF3;
                                    temp |= HAL_EXT_INT_RISING_EDGE << 2;
                                    MCUCR = temp;
                case HAL_AVR_INT2 : MCUCSR |= BV(ISC2);break;
                default: return(HAL_EXT_INT_ERROR);
            };
            break;
         default:
            return(HAL_EXT_INT_ERROR);
    }
    return(HAL_EXT_INT_OK);
}


//----------------------------------------------------------------------------------
//  void _ext_int0_ISR(void)
//
//  DESCRIPTION:
//    INT0 interrupt entry function
//
//  ARGUMENTS:
//    None
//
//  RETURNS:
//    None
//----------------------------------------------------------------------------------
#pragma vector=INT0_vect
__interrupt void _ext_int0_ISR(void)
{
    if((GICR & (BV(INT0))) && (ext_int0_isr != 0))
    {
       ext_int0_isr();    
    }
}

//----------------------------------------------------------------------------------
//  void _ext_int1_ISR(void)
//
//  DESCRIPTION:
//    INT1 interrupt entry function
//
//  ARGUMENTS:
//    None
//
//  RETURNS:
//    None
//----------------------------------------------------------------------------------
#pragma vector=INT1_vect
__interrupt void _ext_int1_ISR(void)
{
    if((GICR & (BV(INT1))) && (ext_int1_isr != 0))
    {
       ext_int1_isr();    
    }
}

//----------------------------------------------------------------------------------
//  void _ext_int2_ISR(void)
//
//  DESCRIPTION:
//    INT2 interrupt entry function
//
//  ARGUMENTS:
//    None
//
//  RETURNS:
//    None
//----------------------------------------------------------------------------------
#pragma vector=INT2_vect
__interrupt void _ext_int2_ISR(void)
{
    if((GICR & (BV(INT2))) && (ext_int2_isr != 0))
    {
       ext_int2_isr();    
    }
}


